var app = {};

var appConfig = {};

/**
 * app 项目初始化
 */
app.init = function(options) {
	var defaults = {
		// 访问路径
		contextPath : "/" + $.url.segment(0),
		// 请求路径
		apiContextPath : "/" + $.url.segment(0) + "/mvc",
		// 标题名称
		titleName  : "Admin",
		// 标题icon
		titleIcon  : '<i class="fa fa-leaf"></i>',
		// 标题样式
		titleClass : "navbar-brand",
		// 用户名称
		userName   : 'Jason',
		// 标题icon
		userIcon   : '<small>Welcome,</small>',
		// 用户样式
		userClass  : 'user-info',
		// cookie中用户键名
		userCookie : "user_userName",
		// 登出名称
		logoutName : 'Logout',
		// 登出样式
		logoutClass: 'user-menu',
		// 登出icon
		logoutIcon : '<i class="ace-icon fa fa-power-off"></i>',
		// 登出事件
		logoutEvent: 'logout()',
		// 登出地址
		logoutUrl  : '/logout.do',
		// 登陆地址
		loginUrl   : '/login.do',
		// 返回地址参数名
		returnUrlName: 'returnUrl'
	};
	// 合并配置
	app = $.extend(defaults, options);
	// 标题名称
	document.title = app.titleName;
	$( "." + app.titleClass ).html( app.titleIcon + " " + app.titleName );
	// 登录用户信息
	var userName = $.cookie( app.userCookie ) || '';
	// 若无用户名信息，则跳登录页
	if( userName == '' && app.loginUrl != '' ) {
		window.location.href = app.loginUrl;
	}
	// 用户名称
	app.userName = userName || app.userName;
	$( "." + app.userClass ).html( app.userIcon + " " + app.userName );
	// 登出事件
	$( "." + app.logoutClass ).find("li:last-child").html( '<a href="javascript:' + app.logoutEvent + '">' + app.logoutIcon + " " + app.logoutName + '</a>' );
	// 配置信息
	/*$.ajax({
		type: "get",//使用get方法访问后台
		dataType: "json",//返回json格式的数据
		url: path.system.query + "/list",//要访问的后台地址
		async:false,
		success:function(data){
			$.each(data.message,function(index,val) {
				appConfig[val.code] = val.name;
			});
		}
	});*/
};

// 获取用户名
function getUserName(){
	var userName = $.cookie(app.userCookie);
	return userName;
};

// 退出
function logout(){
	$.cookie(app.userCookie,null);
	if( app.loginUrl !== '' ) window.location.href = app.loginUrl;
}

//获取图片完整地址
function getImgUrl( url ){
	var url = url.indexOf('//') !== -1 ? url : statusConfig["imgDefaultUrl"] + url;
}

// 跳转页面
function changeAjaxContent( hash, target, serve ){
	var target = target || 'parent', serve = serve || '';
	var href = serve == '' ? app.apiContextPath : statusConfig[serve+"Url"];
	if( target == 'blank' ) {
		window.open(href + hash);
	} else {
		window.location.href = ( hash.indexOf('#page') == -1 ? '#page' + ( hash.substr(0,1) == '/' ? '' : '/' ) : '' ) + hash;
	}
	//$('[data-ajax-content=true]').ace_ajax('loadUrl',hash);
}

// 导出Excel
function exportExcel( url ){
	url = ( url.indexOf("//") == -1 ? app.apiContextPath : '') + url;
	var urlArr = url.split('/');
	$.ajax({
		type: "post",
		dataType: "json",
		url: url,
		data: {},
		async: false,
		success: function(data){
			if( data.isOk == 1 ) {
				var _data = data.result || {}, filename = urlArr[urlArr.length - 2] + (new Date()).format("yyyyMMddhhmmssS") + ".xlsx", ws_name = "Sheet1";
				var wb = XLSX.utils.book_new(), ws = XLSX.utils.json_to_sheet(_data);
				XLSX.utils.book_append_sheet(wb, ws, ws_name);
				XLSX.writeFile(wb, filename);
			} else {
				showMsg(data.message);
			}
		},
		error: function(data){}
	});
}
// 弹出框信息
function showMsg (message, buttons){
	var buttons = buttons || ['success'];
	var btnConfig = {
		success: {
			label: "确定",
			className: "btn-sm btn-primary",
			callback: function(){
			}
		},
		cancel: {
			label: "取消",
			className: "btn-sm",
		}
	};
	var dialogOption = {
		message: message,
		buttons: {}
	};
	$.each(buttons,function(key,val){
		if( typeof val == 'object' ) {
			dialogOption.buttons[val] = val;
		} else if( typeof val == 'string' ) {
			dialogOption.buttons[val] = btnConfig[val];
		}
	});
	bootbox.dialog(dialogOption);
}

// url参数获取
jQuery.url = function() {
	var segments = {};
	var parsed = {};
	/**
	 * Options object. Only the URI and strictMode values can be changed via the
	 * setters below.
	 */
	var options = {
		url : window.location, // default URI is the page in which the script
								// is running
		strictMode : false, // 'loose' parsing by default
		key : [ "source", "protocol", "authority", "userInfo", "user",
				"password", "host", "port", "relative", "path", "directory",
				"file", "query", "anchor" ], // keys available to query
		q : {
			name : "queryKey",
			parser : /(?:^|&)([^&=]*)=?([^&]*)/g
		},
		parser : {
			strict : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, // less
																																							// intuitive,
																																							// more
																																							// accurate
																																							// to
																																							// the
																																							// specs
			loose : /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
		// more intuitive, fails on relative paths and deviates from specs
		}
	};

	/**
	 * Deals with the parsing of the URI according to the regex above. Written
	 * by Steven Levithan - see credits at top.
	 */
	var parseUri = function() {
		str = decodeURI(options.url);
		var m = options.parser[options.strictMode ? "strict" : "loose"]
				.exec(str);
		var uri = {};
		var i = 14;
		while (i--) {
			uri[options.key[i]] = m[i] || "";
		}
		uri[options.q.name] = {};
		uri[options.key[12]].replace(options.q.parser, function($0, $1, $2) {
			if ($1) {
				uri[options.q.name][$1] = $2;
			}
		});
		return uri;
	};

	/**
	 * Returns the value of the passed in key from the parsed URI.
	 * 
	 * @param string
	 *            key The key whose value is required
	 */
	var key = function(key) {
		if (jQuery.isEmptyObject(parsed)) {
			setUp(); // if the URI has not been parsed yet then do this
						// first...
		}
		if (key == "base") {
			if (parsed.port !== null && parsed.port !== "") {
				return parsed.protocol + "://" + parsed.host + ":"
						+ parsed.port + "/";
			} else {
				return parsed.protocol + "://" + parsed.host + "/";
			}
		}
		return (parsed[key] === "") ? null : parsed[key];
	};

	/**
	 * Returns the value of the required query string parameter.
	 * 
	 * @param string
	 *            item The parameter whose value is required
	 */
	var param = function(item) {
		if (jQuery.isEmptyObject(parsed)) {
			setUp(); // if the URI has not been parsed yet then do this
						// first...
		}
		return (parsed.queryKey[item] === null) ? null : parsed.queryKey[item];
	};

	/**
	 * 'Constructor' (not really!) function. Called whenever the URI changes to
	 * kick off re-parsing of the URI and splitting it up into segments.
	 */
	var setUp = function() {
		parsed = parseUri();

		getSegments();
	};

	/**
	 * Splits up the body of the URI into segments (i.e. sections delimited by
	 * '/')
	 */
	var getSegments = function() {
		var p = parsed.path;
		segments = []; // clear out segments array
		segments = parsed.path.length == 1 ? {}
				: (p.charAt(p.length - 1) == "/" ? p.substring(1, p.length - 1)
						: p.substring(1)).split("/");
	};

	return {

		/**
		 * Sets the parsing mode - either strict or loose. Set to loose by
		 * default.
		 * 
		 * @param string
		 *            mode The mode to set the parser to. Anything apart from a
		 *            value of 'strict' will set it to loose!
		 */
		setMode : function(mode) {
			options.strictMode = mode == "strict" ? true : false;
			return this;
		},

		/**
		 * Sets URI to parse if you don't want to to parse the current page's
		 * URI. Calling the function with no value for newUri resets it to the
		 * current page's URI.
		 * 
		 * @param string
		 *            newUri The URI to parse.
		 */
		setUrl : function(newUri) {
			options.url = newUri === undefined ? window.location : newUri;
			setUp();
			return this;
		},

		/**
		 * Returns the value of the specified URI segment. Segments are numbered
		 * from 1 to the number of segments. For example the URI
		 * http://test.com/about/company/ segment(1) would return 'about'.
		 * 
		 * If no integer is passed into the function it returns the number of
		 * segments in the URI.
		 * 
		 * @param int
		 *            pos The position of the segment to return. Can be empty.
		 */
		segment : function(pos) {
			if (jQuery.isEmptyObject(parsed)) {
				setUp(); // if the URI has not been parsed yet then do this
							// first...
			}
			if (pos === undefined) {
				return segments.length;
			}
			return (segments[pos] === "" || segments[pos] === undefined) ? null
					: segments[pos];
		},
		attr : key, // provides public access to private 'key' function - see
					// above
		param : param
	// provides public access to private 'param' function - see above
	};
}();

/**
 * HashMap 的实现
 * 
 * @constructor
 */
function HashMap() {
	/** Map大小* */
	var size = 0;
	/** 对象* */
	var entry = new Object();
	/** Map的存put方法* */
	this.put = function(key, value) {
		if (!this.containsKey(key)) {
			size++;
			entry[key] = value;
		}
	}
	/** Map取get方法* */
	this.get = function(key) {
		return this.containsKey(key) ? entry[key] : null;
	}
	/** Map删除remove方法* */
	this.remove = function(key) {
		if (this.containsKey(key) && (delete entry[key])) {
			size--;
		}
	}
	/** 是否包含Key* */
	this.containsKey = function(key) {
		return (key in entry);
	}
	/** 是否包含Value* */
	this.containsValue = function(value) {
		for ( var prop in entry) {
			if (entry[prop] == value) {
				return true;
			}
		}
		return false;
	}
	/** 所有的Value* */
	this.values = function() {
		var values = new Array();
		for ( var prop in entry) {
			values.push(entry[prop]);
		}
		return values;
	}
	/** 所有的 Key* */
	this.keys = function() {
		var keys = new Array();
		for ( var prop in entry) {
			keys.push(prop);
		}
		return keys;
	}
	/** Map size* */
	this.size = function() {
		return size;
	}
	/** 清空Map* */
	this.clear = function() {
		size = 0;
		entry = new Object();
	}
}

/**
 * 弹出层
 * 
 * @constructor
 */
function dialog(message, buttons) {
	var buttons = buttons || ['success'];
	var btnConfig = {
		success: {
			 label: "确定",
			 className: "btn-sm btn-primary",
			 callback: function(){}
		 },
		cancel: {
			label: "取消",
			className: "btn-sm",
		}
	};
	var dialogOption = {
		message: message,
		buttons: {}
	};
	$.each(buttons,function(key,val){
		if( typeof val == 'object' ) {
			dialogOption.buttons[val] = val;
		} else if( typeof val == 'string' ) {
			dialogOption.buttons[val] = btnConfig[val];
		}
	});
	bootbox.dialog(dialogOption);
}

/**
 * 复写jQuery的Ajax 方法
 */
(function($) {
	var ajax = $.ajax;
	$.ajax = function(opt) {
		var fn = {
			error : function(XMLHttpRequest, textStatus, errorThrown) {},
			success : function(data, textStatus) {},
			complete : function(XMLHttpRequest, textStatus, responseText) {}
		};
		if (opt.error) fn.error = opt.error;
		if (opt.success) fn.success = opt.success;
		if (opt.complete) fn.complete = opt.complete;
		if (opt.context) fn.context = $.extend({}, opt.context);

		// 扩展增强处理
		var _opt = $.extend(opt,
			{
				error : function(XMLHttpRequest, textStatus,errorThrown) {
					// 错误方法增强处理
					var status = XMLHttpRequest.status;
					var message = status + '出错了,请联系管理员!';
					dialog(message);
					fn.error.call(this, XMLHttpRequest, textStatus,errorThrown);
				},
				success : function(data, textStatus) {
					// 校验是否登录
					/*if (data.message == "52000") {
						window.location.href = app.contextPath + "/login.html";
						return;
					}*/
					// 成功回调方法增强处理
					var status = data.status;
					if (status == "ERROR") {
						dialog(data.message);
						return;
					}
					fn.success.call(this, data, textStatus);
				},
				// 传入statusCode对象，定义对状态码操作的方法
				statusCode : {
					// 900为服务器返回的自定义状态码，说明当前操作没有权限
					900 : function() {
						dialog("您没有权限进行此项操作，请联系管理员！");
						return;
					},
					// 901为服务器返回的自定义状态码，说明当前操作未登录
					901 : function() {
						var dialogBtn = {
							success: {
								label: "确定",
								className: "btn-sm btn-primary",
								callback: function(){
									window.location.href = app.apiContextPath + app.loginUrl + "?" + app.returnUrlName + '=' ;
								}
							}
						};
						dialog("您的用户信息已失效，请重新登录！",dialogBtn);
						return;
					}
				}
			});
		return ajax(_opt);
	};
	$.fn.form2json = function() {
		var serializedParams = this.serialize();
		var obj = paramString2obj(serializedParams);
		var str = decodeURIComponent(JSON.stringify(obj));
		return str; // $.parseJSON(str);
	};
})(jQuery);

function obj2JsonStr(o) {
	if (o == undefined) {
		return "";
	}
	var r = [];
	if (typeof o == "string")
		return "\""
				+ o.replace(/([\"\\])/g, "\\$1").replace(/(\n)/g, "\\n")
						.replace(/(\r)/g, "\\r").replace(/(\t)/g, "\\t") + "\"";
	if (typeof o == "object") {
		if (!o.sort) {
			for ( var i in o)
				r.push("\"" + i + "\":" + obj2JsonStr(o[i]));
			if (!!document.all
					&& !/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/
							.test(o.toString)) {
				r.push("toString:" + o.toString.toString());
			}
			r = "{" + r.join() + "}"
		} else {
			for (var i = 0; i < o.length; i++)
				r.push(obj2JsonStr(o[i]))
			r = "[" + r.join() + "]";
		}
		return r;
	}
	return o.toString().replace(/\"\:/g, '":""');
}

function obj2JsonStrForAdd(o) {
	if (o == undefined) {
		return "";
	}
	var r = [];
	if (typeof o == "string")
		return "\"" + o.replace(/([\"\\])/g, "\\$1").replace(/(\n)/g, "\\n").replace(/(\r)/g, "\\r").replace(/(\t)/g, "\\t") + "\"";
	if (typeof o == "object") {
		for ( var i in o)
			r.push("\"" + i + "\":" + obj2JsonStr(o[i]));
		if (!!document.all
				&& !/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/
						.test(o.toString)) {
			r.push("toString:" + o.toString.toString());
		}
		r = "{" + r.join() + "}"
		return r;
	}
	return o.toString().replace(/\"\:/g, '":""');
}

function paramString2obj(serializedParams) {
	var obj = {};
	function evalThem(str) {
		var attributeName = str.split("=")[0];
		var attributeValue = str.split("=")[1];
		if (!attributeValue) {
			return;
		}
		var array = attributeName.split(".");
		for (var i = 1; i < array.length; i++) {
			var tmpArray = Array();
			tmpArray.push("obj");
			for (var j = 0; j < i; j++) {
				tmpArray.push(array[j]);
			}
			;
			var evalString = tmpArray.join(".");
			// alert(evalString);
			if (!eval(evalString)) {
				eval(evalString + "={};");
			}
		}
		eval("obj." + attributeName + "='" + attributeValue + "';");
	}
	var properties = serializedParams.split("&");
	for (var i = 0; i < properties.length; i++) {
		evalThem(properties[i]);
	}
	return obj;
}

/**
 * 将 类似 "object.name":'test' 转成 'object':{name:'test'} 
 * 将 类似 "object.name":'test1,test2,test3' 转成 object:[{name:'test1'},{name:'test2'},{name:'test3'}]
 * 
 * @param dataObj
 * @returns {___anonymous9165_9166}
 */
function param2obj(dataObj) {
	var obj = {};
	function evalThem(key, value) {
		if (!value) {
			return;
		}
		var array = key.split(".");
		var valArray = (typeof value == "object") ? '' : value.split(",");
		for (var i = 1; i < array.length; i++) {
			var tmpArray = Array();
			tmpArray.push("obj");
			for (var j = 0; j < i; j++) {
				tmpArray.push(array[j]);
			}
			;
			var evalString = tmpArray.join(".");
			// alert(evalString);
			if (!eval(evalString)) {
				if (valArray.length > 1) {
					eval(evalString + "=[];");
				} else {
					eval(evalString + "={};");
				}
			}
		}
		if (valArray.length > 1) {
			$.each(valArray,
					function(index, val) {
						var arrayObj = {};
						if (array.length > 1) {
							arrayObj[key.substr(key.indexOf(".") + 1, key.length)] = val;
						}
						eval("obj."
								+ (array.length > 1 ? key.substr(0, key.indexOf(".")) : key) + "[" + index
								+ "]=" + obj2JsonStr(arrayObj) + ";");
					});
		} else {
			if (typeof value == "object") {
				eval("obj." + key + "=" + obj2JsonStr(value) + ";");
			} else {
				eval("obj." + key + "='" + value + "';");
			}
		}
	}
	$.each(dataObj, function(index, val) {
		evalThem(index, val);
	});
	return obj;
}

jQuery.extend({
			/**
			 * 1. 设置cookie的值，把name变量的值设为value example $.cookie(’name’, ‘value’);
			 * 2.新建一个cookie 包括有效期 路径 域名等 example $.cookie(’name’, ‘value’,
			 * {expires: 7, path: ‘/’, domain: ‘jquery.com’, secure: true});
			 * 3.新建cookie example $.cookie(’name’, ‘value’); 4.删除一个cookie
			 * example $.cookie(’name’, null); 5.取一个cookie(name)值给myvar var
			 * account= $.cookie('name');
			 */
			cookie : function(name, value, options) {
				if (typeof value != 'undefined') { // name and value given, set
													// cookie
					options = options || {};
					if (value === null) {
						value = '';
						options.expires = -1;
					}
					var expires = '';
					if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
						var date;
						if (typeof options.expires == 'number') {
							date = new Date();
							date.setTime(date.getTime()
									+ (options.expires * 24 * 60 * 60 * 1000));
						} else {
							date = options.expires;
						}
						expires = '; expires=' + date.toUTCString(); // use
																		// expires
																		// attribute,
																		// max-age
																		// is
																		// not
																		// supported
																		// by IE
					}
					var path = options.path ? '; path=' + options.path : '';
					var domain = options.domain ? '; domain=' + options.domain : '';
					var secure = options.secure ? '; secure' : '';
					document.cookie = [ name, '=', encodeURIComponent(value), expires, path, domain, secure ].join('');
				} else { // only name given, get cookie
					var cookieValue = null;
					if (document.cookie && document.cookie != '') {
						var cookies = document.cookie.split(';');
						for (var i = 0; i < cookies.length; i++) {
							var cookie = jQuery.trim(cookies[i]);
							// Does this cookie string begin with the name we
							// want?
							if (cookie.substring(0, name.length + 1) == (name + '=')) {
								cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
								break;
							}
						}
					}
					return cookieValue;
				}
			}
		});

/**
 * 格式化
 */
String.prototype.format = function(args) {
	var result = this;
	if (arguments.length > 0) {
		if (arguments.length == 1 && typeof (args) == "object") {
			for ( var key in args) {
				if (args[key] != undefined) {
					var reg = new RegExp("({" + key + "})", "g");
					result = result.replace(reg, args[key]);
				}
			}
		} else {
			for (var i = 0; i < arguments.length; i++) {
				if (arguments[i] != undefined) {
					var reg = new RegExp("({)" + i + "(})", "g");
					result = result.replace(reg, arguments[i]);
				}
			}
		}
	}
	return result;
};

/**
 * 单引号转成双引号
 */
String.prototype.replaceAll = function(reallyDo, replaceWith, ignoreCase) {
	if (!RegExp.prototype.isPrototypeOf(reallyDo)) {
		return this.replace(new RegExp(reallyDo, (ignoreCase ? "gi" : "g")), replaceWith);
	} else {
		return this.replace(reallyDo, replaceWith);
	}
}

//对Date的扩展，将 Date 转化为指定格式的String
//月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
//年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
//例子：
//(new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
//(new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
Date.prototype.format = function(fmt) { // author: meizz
	var o = {
		"M+" : this.getMonth() + 1, // 月份
		"d+" : this.getDate(), // 日
		"h+" : this.getHours(), // 小时
		"m+" : this.getMinutes(), // 分
		"s+" : this.getSeconds(), // 秒
		"q+" : Math.floor((this.getMonth() + 3) / 3), // 季度
		"S" : this.getMilliseconds()
	// 毫秒
	};
	if (/(y+)/.test(fmt))
		fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "")
				.substr(4 - RegExp.$1.length));
	for ( var k in o)
		if (new RegExp("(" + k + ")").test(fmt))
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k])
					: (("00" + o[k]).substr(("" + o[k]).length)));
	return fmt;
};
